/**
 * Shows an error dialog if getting a adapter or device wasn't successful,
 * or if/when the device is lost or has an uncaptured error.
 */
export function quitIfWebGPUNotAvailable(
    adapter: GPUAdapter | null,
    device: GPUDevice | null,
): asserts device
{
    if (!device)
    {
        quitIfAdapterNotAvailable(adapter);
        fail('Unable to get a device for an unknown reason');

        return;
    }

    device.lost.then((reason) =>
    {
        fail(`Device lost ("${reason.reason}"):\n${reason.message}`);
    });
    device.onuncapturederror = (ev) =>
    {
        fail(`Uncaptured error:\n${ev.error.message}`);
    };
}

/** Shows an error dialog if getting an adapter wasn't successful. */
function quitIfAdapterNotAvailable(
    adapter: GPUAdapter | null,
): asserts adapter
{
    if (!('gpu' in navigator))
    {
        fail('navigator.gpu is not defined - WebGPU not available in this browser');
    }

    if (!adapter)
    {
        fail("requestAdapter returned null - this sample can't run on this system");
    }
}

/** Fail by showing a console error, and dialog box if possible. */
const fail = (() =>
{
    type ErrorOutput = { show(msg: string): void };

    function createErrorOutput()
    {
        if (typeof document === 'undefined')
        {
            // Not implemented in workers.
            return {
                show(msg: string)
                {
                    console.error(msg);
                },
            };
        }

        const dialogBox = document.createElement('dialog');

        dialogBox.close();
        document.body.append(dialogBox);

        const dialogText = document.createElement('pre');

        dialogText.style.whiteSpace = 'pre-wrap';
        dialogBox.append(dialogText);

        const closeBtn = document.createElement('button');

        closeBtn.textContent = 'OK';
        closeBtn.onclick = () => dialogBox.close();
        dialogBox.append(closeBtn);

        return {
            show(msg: string)
            {
                // Don't overwrite the dialog message while it's still open
                // (show the first error, not the most recent error).
                if (!dialogBox.open)
                {
                    if (msg.indexOf('allow_unsafe_apis') > -1)
                    {
                        msg += '\n\n使用到了您的浏览器不支持的特性，请更换您的浏览器试试。';
                    }

                    dialogText.textContent = msg;
                    dialogBox.showModal();
                }
            },
        };
    }

    let output: ErrorOutput | undefined;

    return (message: string) =>
    {
        if (!output) output = createErrorOutput();

        // output.show(message);
        throw new Error(message);
    };
})();
